package com.qqim.server;

import com.qqim.common.entity.User;
import com.qqim.common.protocol.Protocol;
import com.qqim.common.utils.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * QQ即时通信服务器
 */
public class QQIMServer {
    private static final Logger logger = LoggerFactory.getLogger(QQIMServer.class);
    
    private final String host;
    private final int port;
    private final ServerMain serverMain;
    
    private ServerSocket serverSocket;
    private ExecutorService executorService;
    private final AtomicBoolean running = new AtomicBoolean(false);
    
    /** 在线用户管理 */
    private final ConcurrentHashMap<String, User> onlineUsers = new ConcurrentHashMap<>();
    
    /** 客户端连接管理 */
    private final ConcurrentHashMap<String, ClientHandler> clientHandlers = new ConcurrentHashMap<>();
    
    public QQIMServer(String host, int port, ServerMain serverMain) {
        this.host = host;
        this.port = port;
        this.serverMain = serverMain;
        this.executorService = Executors.newCachedThreadPool(r -> {
            Thread thread = new Thread(r);
            thread.setDaemon(true);
            thread.setName("QQIMServer-" + thread.getId());
            return thread;
        });
    }
    
    /**
     * 启动服务器
     */
    public void start() throws IOException {
        if (running.get()) {
            return;
        }
        
        serverSocket = new ServerSocket(port);
        running.set(true);
        
        logger.info("服务器启动成功，监听地址: {}:{}", host, port);
        serverMain.addLog("服务器启动成功，等待客户端连接...");
        
        // 启动接受连接的线程
        executorService.submit(this::acceptConnections);
    }
    
    /**
     * 停止服务器
     */
    public void stop() {
        if (!running.get()) {
            return;
        }
        
        running.set(false);
        
        // 关闭所有客户端连接
        for (ClientHandler handler : clientHandlers.values()) {
            handler.close();
        }
        clientHandlers.clear();
        onlineUsers.clear();
        
        // 关闭服务器Socket
        if (serverSocket != null && !serverSocket.isClosed()) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                logger.error("关闭服务器Socket失败", e);
            }
        }
        
        // 关闭线程池
        if (executorService != null && !executorService.isShutdown()) {
            executorService.shutdown();
        }
        
        logger.info("服务器已停止");
        serverMain.addLog("服务器已停止");
        serverMain.updateClientCount(0);
    }
    
    /**
     * 接受客户端连接
     */
    private void acceptConnections() {
        while (running.get() && !serverSocket.isClosed()) {
            try {
                Socket clientSocket = serverSocket.accept();
                String clientInfo = clientSocket.getRemoteSocketAddress().toString();
                
                logger.info("新客户端连接: {}", clientInfo);
                serverMain.addLog("新客户端连接: " + clientInfo);
                
                // 为每个客户端创建处理器
                ClientHandler handler = new ClientHandler(clientSocket, this);
                executorService.submit(handler);
                
            } catch (IOException e) {
                if (running.get()) {
                    logger.error("接受客户端连接失败", e);
                    serverMain.addLog("接受客户端连接失败: " + e.getMessage());
                }
            }
        }
    }
    
    /**
     * 用户登录
     */
    public synchronized boolean userLogin(String userId, String nickname, ClientHandler handler) {
        if (onlineUsers.containsKey(userId)) {
            // 用户已在线，拒绝登录
            return false;
        }
        
        User user = new User(userId, nickname);
        onlineUsers.put(userId, user);
        clientHandlers.put(userId, handler);
        
        logger.info("用户登录: {} [{}]", nickname, userId);
        serverMain.addLog("用户登录: " + nickname + " [" + userId + "]");
        serverMain.updateClientCount(onlineUsers.size());
        
        // 通知其他用户有新用户上线
        broadcastUserOnline(userId);
        
        return true;
    }
    
    /**
     * 用户登出
     */
    public synchronized void userLogout(String userId) {
        if (userId != null && onlineUsers.containsKey(userId)) {
            User user = onlineUsers.remove(userId);
            clientHandlers.remove(userId);
            
            logger.info("用户登出: {} [{}]", user.getNickname(), userId);
            serverMain.addLog("用户登出: " + user.getNickname() + " [" + userId + "]");
            serverMain.updateClientCount(onlineUsers.size());
            
            // 通知其他用户有用户下线
            broadcastUserOffline(userId);
        }
    }
    
    /**
     * 转发消息
     */
    public void forwardMessage(String senderId, String receiverId, Protocol protocol) {
        ClientHandler receiverHandler = clientHandlers.get(receiverId);
        if (receiverHandler != null) {
            receiverHandler.sendMessage(protocol);
            logger.debug("消息转发成功: {} -> {}", senderId, receiverId);
        } else {
            logger.warn("目标用户不在线: {}", receiverId);
            // 可以在这里实现离线消息存储
        }
    }
    
    /**
     * 广播用户上线通知
     */
    private void broadcastUserOnline(String userId) {
        Protocol protocol = Protocol.userOnline(userId);
        broadcast(protocol, userId);
    }
    
    /**
     * 广播用户下线通知
     */
    private void broadcastUserOffline(String userId) {
        Protocol protocol = Protocol.userOffline(userId);
        broadcast(protocol, userId);
    }
    
    /**
     * 广播消息（排除指定用户）
     */
    private void broadcast(Protocol protocol, String excludeUserId) {
        for (String userId : clientHandlers.keySet()) {
            if (!userId.equals(excludeUserId)) {
                ClientHandler handler = clientHandlers.get(userId);
                if (handler != null) {
                    handler.sendMessage(protocol);
                }
            }
        }
    }
    
    /**
     * 获取在线用户列表
     */
    public ConcurrentHashMap<String, User> getOnlineUsers() {
        return new ConcurrentHashMap<>(onlineUsers);
    }
    
    /**
     * 检查服务器是否运行中
     */
    public boolean isRunning() {
        return running.get();
    }
    
    /**
     * 获取在线用户数量
     */
    public int getOnlineUserCount() {
        return onlineUsers.size();
    }
} 